"""
Problem 93: https://projecteuler.net/problem=93

By using each of the digits from the set, {1, 2, 3, 4}, exactly
once, and making use of the four arithmetic operations (+, -, *, /)
and brackets/parentheses, it is possible to form different positive
integer targets.

For example,

  8 = (4 * (1 + 3)) / 2
  14 = 4 * (3 + 1 / 2)
  19 = 4 * (2 + 3) - 1
  36 = 3 * 4 * (2 + 1)

Note that concatenations of the digits, like 12 + 34, are not
allowed.

Using the set, {1, 2, 3, 4}, it is possible to obtain thirty-one
different target numbers of which 36 is the maximum, and each of
the numbers 1 to 28 can be obtained before encountering the first
non-expressible number.

Find the set of four distinct digits, a < b < c < d, for which
the longest set of consecutive positive integers, 1 to n, can
be obtained, giving your answer as a string: abcd.

"""

from itertools import permutations
from itertools import combinations_with_replacement


def arithmeticOperations(*args) -> int:
    '''
    >>> assert arithmeticOperations(1,2,3,4) == 28
    '''

    res = set()

    digits_seqs = list(permutations(args))
    # print(digits_seqs)
    oper_seqs = list(combinations_with_replacement(
        ['+', '-', '*', '/'], len(args)-1))
    # print(oper_seqs)

    for oper_seq in oper_seqs:
        for os in set(permutations(oper_seq)):
            for ds in digits_seqs:
                oss, dss = list(os), list(ds)
                while oss:
                    oper = oss.pop()
                    try:
                        dss[1] = eval(str(dss[0]) + oper + str(dss[1]))
                    except ZeroDivisionError:
                        break
                    dss = dss[1:]

                # print(os,ds,dss)
                if len(dss) == 1 and dss[0] == int(dss[0]):
                    res.add(int(dss[0]))

    # print(sorted(list(res)))
    # [-18, -16, -15, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1,
    # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
    # 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 32, 36]

    if 1 not in res:
        return 0

    maxNum = 1
    while True:
        nextNum = maxNum+1
        if nextNum not in res:
            return maxNum
        else:
            maxNum += 1


def solution(limit: int = 10) -> int:
    res = 0
    A, B, C, D = 0, 1, 2, 3
    for a in range(limit):
        for b in range(a+1, limit):
            for c in range(b+1, limit):
                for d in range(c+1, limit):
                    maxNum = arithmeticOperations(a, b, c, d)
                    # print((a,b,c,d),maxNum)
                    if maxNum > res:
                        res = maxNum
                        A, B, C, D = a, b, c, d

    return str(A)+str(B)+str(C)+str(D), res


if __name__ == "__main__":
    from doctest import testmod

    testmod()
    print(solution())
    # 1256,43
